import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GUI } from 'lil-gui'
import Vertex from './vertex.glsl'
import Fragment from './fragment.glsl'

const gui = new GUI()
const loader = new THREE.TextureLoader()

const map = loader.load('/flag.jpg')

const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 4)
scene.add(camera)

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(window.innerWidth, window.innerHeight)

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

const axHelp = new THREE.AxesHelper(5)
scene.add(axHelp)

const parmas = { color: '#ffffff' }

const geometry = new THREE.PlaneGeometry(3, 3, 32, 32)
const material = new THREE.RawShaderMaterial({
  vertexShader: Vertex,
  fragmentShader: Fragment,
  side: THREE.DoubleSide,
  uniforms: {
    uMap: { value: map },
    uColor: { value: new THREE.Color(parmas.color) },
    uFrequency: { value: new THREE.Vector2(10, 5) },
    uTime: { value: 0 },
  },
})

gui.add(material.uniforms.uFrequency.value, 'x').min(0).max(20)
gui.add(material.uniforms.uFrequency.value, 'y').min(0).max(20)
gui.addColor(parmas, 'color').onChange((value: any) => {
  material.uniforms.uColor.value = new THREE.Color(value)
})

const count = geometry.attributes.position.count
const aRandom = new Float32Array(count)
for (let i = 0; i < count; i++) {
  aRandom[i] = Math.random()
}
geometry.setAttribute('aRandom', new THREE.BufferAttribute(aRandom, 1))

const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)

document.body.appendChild(renderer.domElement)

const clock = new THREE.Clock()

const handleTick = () => {
  const time = clock.getElapsedTime()
  material.uniforms.uTime.value = time
  controls.update()
  renderer.render(scene, camera)
  window.requestAnimationFrame(handleTick)
}

const handleSize = () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()

  renderer.setSize(window.innerWidth, window.innerHeight)
}

window.addEventListener('resize', handleSize)
handleTick()
